#ifndef __MQ_ROUTE_HPP__
#define __MQ_ROUTE_HPP__

#include <iostream>
#include "../mq_comm/mq_msg.pb.h"
#include "../mq_comm/helper.hpp"
#include "../mq_comm/logger.hpp"

namespace mq
{
    class Router
    {
    public:
        /*判断消息的routing_key是否合法*/
        static bool isLegalRoutingKey(const std::string &routing_key)
        {
            // routing_key字符串中只能是由a~z,A~Z,0~9,.,_组成
            for (auto &ch : routing_key)
            {
                if ((ch >= 'a' && ch <= 'z') ||
                    (ch >= 'A' && ch <= 'Z') ||
                    (ch >= '0' && ch <= '9') ||
                    ch == '.' || ch == '_')
                    continue;
                return false;
            }
            return true;
        }

        /*判断绑定消息中binding_key是否合法*/
        static bool isLegalBindingKey(const std::string &binding_key)
        {
            // 1.字符合法性判断
            // binding_key字符串中字符由a~z,A~Z,0~9,.,_,*,#组成
            for (auto &ch : binding_key)
            {
                if ((ch >= 'a' && ch <= 'z') ||
                    (ch >= 'A' && ch <= 'Z') ||
                    (ch >= '0' && ch <= '9') ||
                    ch == '.' || ch == '_' ||
                    ch == '*' || ch == '#')
                    continue;
                return false;
            }
            // 2.单词,*,#必须单独存在
            std::vector<std::string> arry;
            StrHelper::split(binding_key, ".", &arry);
            for (auto &str : arry)
            {
                if (str.size() > 1 && (str.find("*") != std::string::npos || str.find("#") != std::string::npos))
                    return false;
            }
            // 3.#前后不允许出现*,#
            for (int i = 1; i < arry.size(); i++)
            {
                if (arry[i] == "#" && arry[i - 1] == "*")
                    return false;
                if (arry[i] == "#" && arry[i - 1] == "#")
                    return false;
                if (arry[i] == "*" && arry[i - 1] == "#")
                    return false;
            }
            return true;
        }

        /*
            根据不同交换机类型判断路由是否正确
            1.广播交换:直接返回true
            2.直接交换:routing_key==binding_key相等直接返回
            3.主题交换:routing_key跟binding_key匹配成功,返回true,失败返回false
        */
        static bool route(ExchangeType type, const std::string &routing_key, const std::string &binding_key)
        {
            if (type == ExchangeType::FANOUT)
                return true;
            if (type == ExchangeType::DIRECT)
            {
                if(routing_key == binding_key) return true;
                return false;
            }
            // 1.切分
            std::vector<std::string> routing_arry;
            std::vector<std::string> binding_arry;
            StrHelper::split(routing_key, ".", &routing_arry);
            StrHelper::split(binding_key, ".", &binding_arry);
            // 2.动态规划判断
            size_t routing_size = routing_arry.size();
            size_t binding_size = binding_arry.size();
            std::vector<std::vector<bool>> dp(binding_size + 1, std::vector<bool>(routing_size + 1, false));
            dp[0][0] = true;
            for (int i = 1; i <= binding_size; i++)
            {
                if (binding_arry[i - 1] == "#")
                {
                    dp[i][0] = true;
                    continue;
                }
                break;
            }

            for (int i = 1; i <= binding_size; i++)
            {
                for (int j = 1; j <= routing_size; j++)
                {
                    if (binding_arry[i - 1] == routing_arry[j - 1] || binding_arry[i - 1] == "*")
                    {
                        dp[i][j] = dp[i - 1][j - 1];
                    }
                    else if (binding_arry[i - 1] == "#")
                    {
                        dp[i][j] = dp[i - 1][j - 1] | dp[i - 1][j] | dp[i][j - 1];
                    }
                }
            }
            return dp[binding_size][routing_size];
        }
    };
}

#endif